package com.usian.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageInfo;
import com.usian.common.dto.CourseDTO;
import com.usian.common.dto.PaperDTO;
import com.usian.common.dto.TeamDTO;
import com.usian.common.dto.TrainingDTO;
import com.usian.common.model.course.Course;
import com.usian.common.model.member.Member;
import com.usian.common.model.paper.Paper;
import com.usian.common.untils.Result;
import com.usian.common.vo.CourseVO;
import com.usian.common.vo.PaperVO;
import com.usian.common.vo.TrainingVO;
import com.usian.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @projectName: 2210A-project1
 * @package: com.usian.controller
 * @className: IndexController
 * @author: 莫洪维
 * @email: 1204315800@qq.com
 * @description: TODO
 * @date: 2023/8/23 18:28
 */
@RestController
@RequestMapping("/homePage")
public class IndexController {

    private final Integer NEW_FIND_METHOD = 1;
    private final Integer HOT_FIND_METHOD = 2;

    @Autowired
    private CompetitionFeignService competitionFeignService;
    @Autowired
    private TrainingFeignService trainingFeignService;
    @Autowired
    private CourseFeignService courseFeignService;
    @Autowired
    private PaperFeignService paperFeignService;
    @Autowired
    private TeamFeignService teamFeignService;
    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 获取登录人数据
     * @param request
     * @return
     */
    @RequestMapping(value = "/findLoginMember",method = RequestMethod.GET)
    public Result findLoginMember(HttpServletRequest request){
        //获取token
        String token = request.getHeader("token");
        Object login = redisTemplate.opsForValue().get(token);
        Member member = JSONUtil.toBean(String.valueOf(login), Member.class);
        return Result.ok().message("查询成功").data("member",member);
    }

    /**
     * 查询所有战队方法
     * @param
     * @return
     */
    @RequestMapping(value = "/findAllTeam",method = RequestMethod.GET)
    public Result findAllTeam(TeamDTO teamDTO){
        //查询所有战队方法
        Result result = teamFeignService.findAll(teamDTO);
        return result;
    }

    /**
     * 查询所有标签方法
     * */
    @RequestMapping(value = "/labelList",method = RequestMethod.GET)
    public Result findLabelList(){
        //调用方法进行查询
        return courseFeignService.findLabelList();
    }

    /**
     * 根据查询状态查询测验
     * */
    @RequestMapping(value = "/newPaper",method = RequestMethod.GET)
    public Result newPaper(Integer limitNum, PaperDTO paperDTO){
        //调用方法进行查询
        PageInfo<PaperVO> pageInfo = paperFeignService.list(paperDTO);
        List<PaperVO> paperVOList = pageInfo.getList();
        paperVOList = toPaperNum(paperVOList);

        Comparator<PaperVO> comparator;
        if (paperDTO.getFindMethod().equals(HOT_FIND_METHOD)){
            // 找出最热的前limitNum个测验
            comparator = Comparator.comparing(PaperVO::getStudyNum).reversed();
        } else if (paperDTO.getFindMethod().equals(NEW_FIND_METHOD)){
            // 找出最新的前limitNum个测验
            comparator = Comparator.comparing(PaperVO::getId).reversed();
        } else {
            comparator = null;
        }

        if (comparator != null) {
            paperVOList = paperVOList.stream()
                    .sorted(comparator)
                    .limit(limitNum)
                    .collect(Collectors.toList());
        }

        pageInfo.setList(paperVOList);
        return Result.ok().message("查询成功").data("newPaper", pageInfo);
    }

    /**
     * 封装测验数据方法
     * @param paperVOList
     * @return
     */
    private List<PaperVO> toPaperNum(List<PaperVO> paperVOList){
        for (int i = 0; i < paperVOList.size(); i++) {
            PaperVO paperVO = paperVOList.get(i);
            //多少人参加
            Integer studyNum = trainingFeignService.paperMemberNum(paperVO.getId());
            paperVO.setStudyNum(studyNum);
            //多少道题
            Integer questionsNum = paperFeignService.paperQuestionsNum(paperVO.getId());
            paperVO.setQuestionsNum(questionsNum);
            paperVOList.set(i,paperVO);
        }
        return paperVOList;
    }

    /**
     * 最新,最热,综合培训
     * */
    @RequestMapping(value = "/newTraining",method = RequestMethod.GET)
    public Result newTraining(Integer limit,TrainingDTO trainingDTO){
        PageInfo<TrainingVO> pageInfo = trainingFeignService.list(trainingDTO);
        List<TrainingVO> list = pageInfo.getList();

        // 多线程并发处理数据
        list.parallelStream().forEach(trainingVO -> {
            //学习人数
            Integer studyNum = trainingFeignService.trainingMemberNum(trainingVO.getId());
            //课程数量
            Integer courseNum = trainingFeignService.trainingForCourseNum(trainingVO.getId());
            //测验数量
            Integer paperNum = trainingFeignService.trainingPaperNum(trainingVO.getId());

            //判断培训状态
            Date now = new Date();
            if (DateUtil.compare(now, trainingVO.getTrainingStartDate()) < 0) {
                trainingVO.setTrainingPlan("1");
            } else if (DateUtil.compare(now, trainingVO.getTrainingStartDate()) >= 0 && DateUtil.compare(trainingVO.getTrainingEndDate(), now) > 0) {
                trainingVO.setTrainingPlan("2");
            } else {
                trainingVO.setTrainingPlan("3");
            }

            trainingVO.setStudyNum(studyNum);
            trainingVO.setCourseNum(courseNum);
            trainingVO.setPaperNum(paperNum);
        });

        //根据前台传过来的查询方式进行排序
        if (trainingDTO.getFindMethod().equals(NEW_FIND_METHOD)){
            //找出最新的limit个培训
            list = list.stream()
                    .sorted(Comparator.comparing(TrainingVO::getTrainingStartDate).reversed())
                    .limit(limit)
                    .collect(Collectors.toList());
        } else if (trainingDTO.getFindMethod().equals(HOT_FIND_METHOD)){
            //找出最热的limit个培训
            list = list.stream()
                    .sorted(Comparator.comparing(TrainingVO::getStudyNum).reversed())
                    .limit(limit)
                    .collect(Collectors.toList());
        }

        pageInfo.setList(list);
        return Result.ok().message("查询成功").data("newTraining",pageInfo);
    }

    /**
     * 根据id查询课程方法
    * */
    @RequestMapping(value = "/findById",method = RequestMethod.GET)
    public Result findById(Long id){
        //调用方法进行查询
        CourseDTO courseDTO = new CourseDTO();
        courseDTO.setPageSize(1000);
        PageInfo<CourseVO> pageInfo = courseFeignService.list(courseDTO);
        //课程点赞信息
        pageInfo.setList(toLikeNum(pageInfo.getList()));
        CourseVO courseVO = pageInfo.getList().stream()
                .filter(i -> i.getId().equals(id))
                .findAny()
                .get();
        return Result.ok().message("查询成功").data("course",courseVO);
    }

    /**
    * 查询综合、最新、最热课程方法
    * */
    @RequestMapping(value = "/findAllCourse",method = RequestMethod.GET)
    public Result findAllCourse(Integer num,CourseDTO courseDTO){
        //调用方法进行查询
        PageInfo<CourseVO> pageInfo = courseFeignService.list(courseDTO);
        //课程点赞信息
        List<CourseVO> list = toLikeNum(pageInfo.getList());
        //判断查询方式标识符
        if (courseDTO.getFindMethod().equals(NEW_FIND_METHOD)){
            //查询最新课程
            list = list.stream()
                    .sorted(Comparator.comparing(Course::getCreateDate).reversed())
                    .limit(num)
                    .collect(Collectors.toList());
        } else if (courseDTO.getFindMethod().equals(HOT_FIND_METHOD)){
            //查询最热课程
            list = list.stream()
                    .sorted(Comparator.comparing(CourseVO::getLikeNumber).reversed())
                    .limit(num)
                    .collect(Collectors.toList());
        }
        pageInfo.setList(list);
        return Result.ok().message("查询成功").data("courseList",pageInfo);
    }

    /**
    * 查询课程点赞信息方法
    * */
    private List<CourseVO> toLikeNum(List<CourseVO> list){
        //课程点赞信息
        Map<String,Integer> map = redisTemplate.opsForHash().entries("likeCourse");
        for (int i = 0; i < list.size(); i++) {
            CourseVO course = list.get(i);
            Integer likeNum = map.get(course.getId().toString());
            course.setLikeNumber(likeNum);
            course.setStudyNum(trainingFeignService.toCourseStudyNum(course.getId()));
            list.set(i,course);
        }
        return list;
    }

    /**
     *取消点赞方法
     * */
    @RequestMapping(value = "/unlikeCourse",method = RequestMethod.GET)
    public Result unlikeCourse(Long id,Long memberId){
        try {
            this.toLike();
            Integer likeNum = Integer.valueOf(String.valueOf(redisTemplate.opsForHash().get("likeCourse", id.toString())));
            if (likeNum == 0){
                return Result.ok().message("已取消");
            }
            redisTemplate.opsForHash().put("likeCourse",id.toString(),likeNum-1);
            String memberLikeForCourse = String.valueOf(redisTemplate.opsForHash().get("MemberLikeForCourse", memberId.toString()));
            memberLikeForCourse = memberLikeForCourse.replace(","+id,"");
            memberLikeForCourse = memberLikeForCourse.replace(id+",","");
            redisTemplate.opsForHash().put("MemberLikeForCourse", memberId.toString(),memberLikeForCourse);
            return Result.ok().message("已取消");
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return Result.error().message("请稍后重试");
        }
    }

    /**
     * 查询成员点赞信息
     */
    @RequestMapping(value = "/memberLike",method = RequestMethod.GET)
    public Result memberLike(Long memberId){
        Object memberLikeForCourse = redisTemplate.opsForHash().get("MemberLikeForCourse", memberId.toString());
        return Result.ok().data("memberLike",memberLikeForCourse);
    }

    /**
     *将点赞信息存入Redis
     * */
    private void toLike(){
        //调用方法进行查询所有课程点赞信息
        List likeCourse = redisTemplate.opsForHash().values("likeCourse");
        if (likeCourse.isEmpty()){
            CourseDTO courseDTO = new CourseDTO();
            courseDTO.setPageSize(1000);
            List<CourseVO> list = courseFeignService.list(courseDTO).getList();
            list.forEach(i ->{
                redisTemplate.opsForHash().put("likeCourse",i.getId().toString(),0);
            });
        }
    }

    /**
     *点赞方法
     * */
    @RequestMapping(value = "/likeCourse",method = RequestMethod.GET)
    public Result likeCourse(Long id,Long memberId){
        try {
            this.toLike();
            Object likeNum = redisTemplate.opsForHash().get("likeCourse", id.toString());
            redisTemplate.opsForHash().put("likeCourse",id.toString(),Integer.valueOf(String.valueOf(likeNum))+1);
            Object memberLikeForCourse = redisTemplate.opsForHash().get("MemberLikeForCourse", memberId.toString());
            if (memberLikeForCourse == null){
                redisTemplate.opsForHash().put("MemberLikeForCourse", memberId.toString(),id.toString());
            }else  {
                redisTemplate.opsForHash().put("MemberLikeForCourse", memberId.toString(),memberLikeForCourse + "," +id);
            }
            return Result.ok().message("点赞成功");
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return Result.error().message("请稍后重试");
        }
    }

    /**
     *根据成员id查询竞赛数量
     * */
    @RequestMapping(value = "/toCompetitionNum",method = RequestMethod.GET)
    public Result toCompetitionNum(Long memberId){
        //调用方法进行查询
        return competitionFeignService.toCompetitionNum(memberId);
    }

    /**
     *根据成员id查询课程数量方法
     * */
    @RequestMapping(value = "/toCourseNum",method = RequestMethod.GET)
    public Result toCourseNum(Long memberId){
        //调用方法进行查询
        return trainingFeignService.toCourseNum(memberId);
    }

    /**
     *根据成员id查询培训数量
     * */
    @RequestMapping(value = "/countMemberTraining",method = RequestMethod.GET)
    public Result countMemberTraining(Long memberId){
        //调用方法进行查询
        return trainingFeignService.countMemberTraining(memberId);
    }

}
